<template>
  <div class="file-box">
    <el-upload
        :action="action"
        :list-type="listType"
        :multiple="multiple"
        ref="upImg"
        :limit="limit"
        :file-list="fileList"
        :headers="headers"
        :drag="drag"
        :accept="accept"
        :on-success="onSuccess"
        :on-remove="onRemove"
        :before-upload="beforeUpload"
        :on-exceed="handleExceed"
        :on-preview="handlePictureCardPreview"
        :disabled="isDisabled"
    >
      <el-icon v-if="listType==='picture-card'"><Plus /></el-icon>
      <el-button v-else size="small" type="primary" plain style="margin-top: 5px">点击上传</el-button>
      <template #tip>
        <div v-if="drag" class="el-upload__text"><em>支持拖拽上传</em></div>
        <div v-if="accept" class="el-upload__tip" slot="tip">只能上传类型：{{accept}}</div>
        <div v-if="size" class="el-upload__tip" slot="tip">最大不超过：{{size}} M</div>
      </template>

    </el-upload>
    <el-dialog   v-model="dialogVisible" size="tiny" append-to-body width="450px">
      <img v-if="isImg" style="height: 100%;width: 100%" :src="dialogImageUrl" alt="预览">
      <template v-if="dialogVisible&&!isImg">
        <video controls style="width: 100%;height: 100%" >
          <source :src="dialogImageUrl" type="video/mp4" />
          <source :src="dialogImageUrl" type="video/webm" />
          <source :src="dialogImageUrl" type="video/ogg" />
          <source :src="dialogImageUrl" type="video/AVI" />
          <source :src="dialogImageUrl" type="video/FLV" />
          <source :src="dialogImageUrl" type="video/MOV" />
          <source :src="dialogImageUrl" type="video/wmv" />
          <source :src="dialogImageUrl" type="video/mkv" />
        </video>
      </template>
    </el-dialog>
  </div>
</template>

<script setup name="UpFile">
  import {ref,watch} from 'vue'
  import {getToken} from "@/utils/auth.js";
  import useUserStore from "@/store/modules/user";
  import {useRoute,useRouter} from "vue-router";
  const {proxy}=getCurrentInstance();
  const userStore = useUserStore();
  const route=useRoute();
  const router=useRouter();
  const props=defineProps({
    //接收字符串："url,url,url"    数组：[{url:""},{url:""}]或者["url","url"]
    modelValue: [String, Array],
    //modelValue返回格式，string 返回"url,url,url" ；arrayStr 返回["url","url"] ； arrayObj 返回[{url:""},{url:""}]
    runType:{
      type:String,
      default:"string"
    },
    //文件数量 为0 不限制
    limit:{
      type:Number,
      default: 0
    },
    //是否多选
    multiple:{
      type:Boolean,
      default:false
    },
    //是否拖拽
    drag:{
      type:Boolean,
      default:false
    },
    //展示类型  picture-card/picture/text
    listType:{
      default:"picture-card"
    },
    //文件类型 为空不限制 .jpg,.png
    accept:{
      type:String,
      default:""
    },
    //文件大小限制，为0不限制   单位M
    size:{
      type:Number,
      default: 0
    },
    //是否禁用
    isDisabled:{
      type:Boolean,
      default:false
    },
    //是否上传完成马上清除上传显示目录
    isClearFiles:{
      type:Boolean,
      default:false
    },
  });
  const number = ref(0);
  const dialogImageUrl = ref('');
  const dialogVisible = ref(false);
  const action= import.meta.env.VITE_APP_BASE_HOST+'/file/file';
  const headers={token:getToken()};
  const list=ref([]);
  const fileList=ref([]);
  const upImg=ref(null);
  const isImg=ref(true);
  const emit= defineEmits(["upSuccess","upRemove"]);
  watch(() => props.modelValue, val => {
    if (val) {
      // 首先将值转为数组
      const listArr = Array.isArray(val) ? val : props.modelValue.split(",");
      // 然后将数组转为对象数组
      list.value = fileList.value = listArr.map(item => {
        if (typeof item === "string") {
          if (item.indexOf(action) === -1) {
            item = { name: item.name||item, url: item };
          } else {
            item = { name: item.name||item, url: item };
          }
        }
        return item;
      });
    } else {
      list.value = fileList.value = [];
      return [];
    }
  },{ deep: true, immediate: true });

  watch(()=>list,(val)=>{
    emit("update:modelValue", listToString(val.value));
  },{deep:true});

  // 对象转成指定字符串分隔
  function listToString(list, separator) {
    switch (props.runType) {
      case "string":
        let strs = "";
        separator = separator || ",";
        for (let i in list) {
          if (undefined !== list[i].url && list[i].url.indexOf("blob:") !== 0) {
            strs += list[i].url.replace(action, "") + separator;
          }
        }
        return strs != "" ? strs.substr(0, strs.length - 1) : "";
        break;
      case "arrayStr":
        return list.map(t=>t.url);
        break;
      case "arrayObj":
        return list;
        break;
      default :
        return ""
    }

  }

  function getFileRes(){
    return list.value;
  }
  function handlePictureCardPreview(file){
    const {url,name,response}=file;
    const imageRegex = /\.(jpe?g|png|gif|bmp|webp|jpg)$/i;
    const videoRegex = /\.(mp4|AVI|FLV|MOV|wmv|mkv)$/i;
    if(imageRegex.test(name)||imageRegex.test(url)){
      isImg.value=true;
      dialogImageUrl.value = url?url:response.data[0].url;
    }else if(videoRegex.test(name)||videoRegex.test(url)){
      isImg.value=false;
      dialogImageUrl.value =response?response.data[0].url:url;
    }else{
      return window.open(response?response.data[0].url:url)
    }
    dialogVisible.value = true;
  }
  function onSuccess(res){
    let {data,code,msg}=res;
    if(code==203){
      proxy.$modal.msgError("登陆失效，请重新登陆！");
      userStore.logOut().then(() => {
        router.push({path:'/login'})
      });
      number.value--;
      return
    };
    if(code!=1){
      number.value--;
      return proxy.$modal.msgError(msg||"上传失败！");
    }
    list.value=list.value.concat(data);
    emit("upSuccess",{data});
    //根据选择的数量判断为最后一次触发
    if (number.value > 0 && list.value.length === number.value) {
      number.value=0;
      //图片管理使用
      emit("uploadSuccessImgAdmin", list.value);
      // 清除上传文件（/图片管理使用）
      if(props.isClearFiles){
        list.value=[];
        setTimeout(()=>{proxy.$refs.upImg.clearFiles();},500);
      }
    }
  }
  function onRemove(res){
    let {response}=res;
    let data=response?response.data:[res];
    // let index=list.value.findIndex(t=>t.url==data[0].url);
    // list.value.splice(index,1);
    return emit("upRemove",{data});
  }
  function beforeUpload(res){
    if(props.size&&(res.size/1024/1024)>props.size){
      proxy.$modal.msgError(`最大不超过${props.size} M`);
      return false;
    };
    if(props.accept){
      const regex = /\.([^.]*)$/;
      const match = res.name.match(regex);
      const result = match ? match[0] : "";
      if(!props.accept.includes(result)){
        proxy.$modal.msgError(`只能上传类型：${props.accept}`);
        return false;
      }
    }
    number.value++;
    return true;
  }
  function handleExceed(){
    proxy.$modal.msgError(`一次性最多可上传：${props.limit}个`);
  }
  function clearFiles(){
    list.value=[];
    upImg.value.clearFiles();
  }
  defineExpose({
    getFileRes,
    clearFiles
  })
</script>

<style scoped lang="scss">
.file-box{
  :deep(.el-upload-dragger){
    width: 148px;
    height: 148px;
    .el-upload__text{
      width: 100%;
      position: absolute;
      top: 45px;
    }
  }
  :deep(.el-upload__tip){
    line-height: 15px;
  }
}
</style>
